/*
* Copyright (c) 2017, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

#include <vector>
#include "cm_test.h"

// The kernel names is "DoNothing" on all Gen platforms.
static uint8_t BROADWELL_DONOTHING_ISA[]
= {0x43, 0x49, 0x53, 0x41, 0x03, 0x06, 0x01, 0x00, 0x09, 0x44, 0x6f, 0x4e, 0x6f,
   0x74, 0x68, 0x69, 0x6e, 0x67, 0x30, 0x00, 0x00, 0x00, 0x67, 0x01, 0x00, 0x00,
   0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x97, 0x01, 0x00,
   0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
   0x44, 0x6f, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x00, 0x6e, 0x75, 0x6c,
   0x6c, 0x00, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x78, 0x00, 0x74, 0x68,
   0x72, 0x65, 0x61, 0x64, 0x5f, 0x79, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f,
   0x69, 0x64, 0x5f, 0x78, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64,
   0x5f, 0x79, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x5f, 0x7a,
   0x00, 0x74, 0x73, 0x63, 0x00, 0x72, 0x30, 0x00, 0x61, 0x72, 0x67, 0x00, 0x72,
   0x65, 0x74, 0x76, 0x61, 0x6c, 0x00, 0x73, 0x70, 0x00, 0x66, 0x70, 0x00, 0x68,
   0x77, 0x5f, 0x69, 0x64, 0x00, 0x73, 0x72, 0x30, 0x00, 0x63, 0x72, 0x30, 0x00,
   0x63, 0x65, 0x30, 0x00, 0x64, 0x62, 0x67, 0x30, 0x00, 0x63, 0x6f, 0x6c, 0x6f,
   0x72, 0x00, 0x54, 0x30, 0x00, 0x54, 0x31, 0x00, 0x54, 0x32, 0x00, 0x54, 0x33,
   0x00, 0x54, 0x32, 0x35, 0x32, 0x00, 0x54, 0x32, 0x35, 0x35, 0x00, 0x53, 0x33,
   0x31, 0x00, 0x56, 0x33, 0x32, 0x00, 0x56, 0x33, 0x33, 0x00, 0x44, 0x6f, 0x4e,
   0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x42, 0x42, 0x5f, 0x30, 0x5f, 0x31,
   0x00, 0x41, 0x73, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x4e, 0x6f, 0x42, 0x61,
   0x72, 0x72, 0x69, 0x65, 0x72, 0x00, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00,
   0x64, 0x3a, 0x5c, 0x64, 0x6f, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x5f,
   0x67, 0x65, 0x6e, 0x78, 0x2e, 0x63, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x02, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
   0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
   0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x21, 0x00,
   0x00, 0x00, 0x24, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x56, 0x01, 0x00,
   0x00, 0x03, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6f, 0x6e, 0x6f, 0x74,
   0x68, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x65, 0x6e, 0x78, 0x5f, 0x30, 0x2e, 0x61,
   0x73, 0x6d, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00,
   0x30, 0x00, 0x00, 0x51, 0x20, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00,
   0x34, 0x00, 0x00, 0x00, 0x01, 0x4d, 0x00, 0x20, 0x07, 0x7f, 0x00, 0x00, 0x31,
   0x00, 0x00, 0x07, 0x00, 0x3a, 0x00, 0x20, 0xe0, 0x0f, 0x00, 0x06, 0x10, 0x00,
   0x00, 0x82};

static uint8_t SKYLAKE_DONOTHING_ISA[]
= {0x43, 0x49, 0x53, 0x41, 0x03, 0x06, 0x01, 0x00, 0x09, 0x44, 0x6f, 0x4e, 0x6f,
   0x74, 0x68, 0x69, 0x6e, 0x67, 0x30, 0x00, 0x00, 0x00, 0x67, 0x01, 0x00, 0x00,
   0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x97, 0x01, 0x00,
   0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
   0x44, 0x6f, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x00, 0x6e, 0x75, 0x6c,
   0x6c, 0x00, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x78, 0x00, 0x74, 0x68,
   0x72, 0x65, 0x61, 0x64, 0x5f, 0x79, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f,
   0x69, 0x64, 0x5f, 0x78, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64,
   0x5f, 0x79, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x5f, 0x7a,
   0x00, 0x74, 0x73, 0x63, 0x00, 0x72, 0x30, 0x00, 0x61, 0x72, 0x67, 0x00, 0x72,
   0x65, 0x74, 0x76, 0x61, 0x6c, 0x00, 0x73, 0x70, 0x00, 0x66, 0x70, 0x00, 0x68,
   0x77, 0x5f, 0x69, 0x64, 0x00, 0x73, 0x72, 0x30, 0x00, 0x63, 0x72, 0x30, 0x00,
   0x63, 0x65, 0x30, 0x00, 0x64, 0x62, 0x67, 0x30, 0x00, 0x63, 0x6f, 0x6c, 0x6f,
   0x72, 0x00, 0x54, 0x30, 0x00, 0x54, 0x31, 0x00, 0x54, 0x32, 0x00, 0x54, 0x33,
   0x00, 0x54, 0x32, 0x35, 0x32, 0x00, 0x54, 0x32, 0x35, 0x35, 0x00, 0x53, 0x33,
   0x31, 0x00, 0x56, 0x33, 0x32, 0x00, 0x56, 0x33, 0x33, 0x00, 0x44, 0x6f, 0x4e,
   0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x42, 0x42, 0x5f, 0x30, 0x5f, 0x31,
   0x00, 0x41, 0x73, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x4e, 0x6f, 0x42, 0x61,
   0x72, 0x72, 0x69, 0x65, 0x72, 0x00, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00,
   0x64, 0x3a, 0x5c, 0x64, 0x6f, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x5f,
   0x67, 0x65, 0x6e, 0x78, 0x2e, 0x63, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x02, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
   0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
   0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x21, 0x00,
   0x00, 0x00, 0x24, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x56, 0x01, 0x00,
   0x00, 0x03, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6f, 0x6e, 0x6f, 0x74,
   0x68, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x65, 0x6e, 0x78, 0x5f, 0x30, 0x2e, 0x61,
   0x73, 0x6d, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00,
   0x30, 0x00, 0x00, 0x51, 0x20, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00,
   0x34, 0x00, 0x00, 0x00, 0x01, 0x4d, 0x00, 0x20, 0x07, 0x7f, 0x00, 0x00, 0x31,
   0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x20, 0xe0, 0x0f, 0x00, 0x06, 0x10, 0x00,
   0x00, 0x82};

static uint8_t BROXTON_DONOTHING_ISA[]
= {0x43, 0x49, 0x53, 0x41, 0x03, 0x06, 0x01, 0x00, 0x09, 0x44, 0x6f, 0x4e, 0x6f,
   0x74, 0x68, 0x69, 0x6e, 0x67, 0x30, 0x00, 0x00, 0x00, 0x67, 0x01, 0x00, 0x00,
   0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x97, 0x01, 0x00,
   0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
   0x44, 0x6f, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x00, 0x6e, 0x75, 0x6c,
   0x6c, 0x00, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x78, 0x00, 0x74, 0x68,
   0x72, 0x65, 0x61, 0x64, 0x5f, 0x79, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f,
   0x69, 0x64, 0x5f, 0x78, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64,
   0x5f, 0x79, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x5f, 0x7a,
   0x00, 0x74, 0x73, 0x63, 0x00, 0x72, 0x30, 0x00, 0x61, 0x72, 0x67, 0x00, 0x72,
   0x65, 0x74, 0x76, 0x61, 0x6c, 0x00, 0x73, 0x70, 0x00, 0x66, 0x70, 0x00, 0x68,
   0x77, 0x5f, 0x69, 0x64, 0x00, 0x73, 0x72, 0x30, 0x00, 0x63, 0x72, 0x30, 0x00,
   0x63, 0x65, 0x30, 0x00, 0x64, 0x62, 0x67, 0x30, 0x00, 0x63, 0x6f, 0x6c, 0x6f,
   0x72, 0x00, 0x54, 0x30, 0x00, 0x54, 0x31, 0x00, 0x54, 0x32, 0x00, 0x54, 0x33,
   0x00, 0x54, 0x32, 0x35, 0x32, 0x00, 0x54, 0x32, 0x35, 0x35, 0x00, 0x53, 0x33,
   0x31, 0x00, 0x56, 0x33, 0x32, 0x00, 0x56, 0x33, 0x33, 0x00, 0x44, 0x6f, 0x4e,
   0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x42, 0x42, 0x5f, 0x30, 0x5f, 0x31,
   0x00, 0x41, 0x73, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x4e, 0x6f, 0x42, 0x61,
   0x72, 0x72, 0x69, 0x65, 0x72, 0x00, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00,
   0x64, 0x3a, 0x5c, 0x64, 0x6f, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x5f,
   0x67, 0x65, 0x6e, 0x78, 0x2e, 0x63, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x02, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
   0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
   0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x21, 0x00,
   0x00, 0x00, 0x24, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x56, 0x01, 0x00,
   0x00, 0x03, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6f, 0x6e, 0x6f, 0x74,
   0x68, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x65, 0x6e, 0x78, 0x5f, 0x30, 0x2e, 0x61,
   0x73, 0x6d, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00,
   0x30, 0x00, 0x00, 0x51, 0x20, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00,
   0x34, 0x00, 0x00, 0x00, 0x01, 0x4d, 0x00, 0x20, 0x07, 0x7f, 0x00, 0x00, 0x31,
   0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x20, 0xe0, 0x0f, 0x00, 0x06, 0x10, 0x00,
   0x00, 0x82};

static uint8_t CANNONLAKE_DONOTHING_ISA[]
= {0x43, 0x49, 0x53, 0x41, 0x03, 0x06, 0x01, 0x00, 0x09, 0x44, 0x6f, 0x4e, 0x6f,
   0x74, 0x68, 0x69, 0x6e, 0x67, 0x30, 0x00, 0x00, 0x00, 0x67, 0x01, 0x00, 0x00,
   0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x97, 0x01, 0x00,
   0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
   0x44, 0x6f, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x00, 0x6e, 0x75, 0x6c,
   0x6c, 0x00, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x78, 0x00, 0x74, 0x68,
   0x72, 0x65, 0x61, 0x64, 0x5f, 0x79, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f,
   0x69, 0x64, 0x5f, 0x78, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64,
   0x5f, 0x79, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x5f, 0x7a,
   0x00, 0x74, 0x73, 0x63, 0x00, 0x72, 0x30, 0x00, 0x61, 0x72, 0x67, 0x00, 0x72,
   0x65, 0x74, 0x76, 0x61, 0x6c, 0x00, 0x73, 0x70, 0x00, 0x66, 0x70, 0x00, 0x68,
   0x77, 0x5f, 0x69, 0x64, 0x00, 0x73, 0x72, 0x30, 0x00, 0x63, 0x72, 0x30, 0x00,
   0x63, 0x65, 0x30, 0x00, 0x64, 0x62, 0x67, 0x30, 0x00, 0x63, 0x6f, 0x6c, 0x6f,
   0x72, 0x00, 0x54, 0x30, 0x00, 0x54, 0x31, 0x00, 0x54, 0x32, 0x00, 0x54, 0x33,
   0x00, 0x54, 0x32, 0x35, 0x32, 0x00, 0x54, 0x32, 0x35, 0x35, 0x00, 0x53, 0x33,
   0x31, 0x00, 0x56, 0x33, 0x32, 0x00, 0x56, 0x33, 0x33, 0x00, 0x44, 0x6f, 0x4e,
   0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x42, 0x42, 0x5f, 0x30, 0x5f, 0x31,
   0x00, 0x41, 0x73, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x4e, 0x6f, 0x42, 0x61,
   0x72, 0x72, 0x69, 0x65, 0x72, 0x00, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00,
   0x64, 0x3a, 0x5c, 0x64, 0x6f, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x5f,
   0x67, 0x65, 0x6e, 0x78, 0x2e, 0x63, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x02, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
   0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
   0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x21, 0x00,
   0x00, 0x00, 0x24, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x56, 0x01, 0x00,
   0x00, 0x03, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6f, 0x6e, 0x6f, 0x74,
   0x68, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x65, 0x6e, 0x78, 0x5f, 0x30, 0x2e, 0x61,
   0x73, 0x6d, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00,
   0x30, 0x00, 0x00, 0x51, 0x20, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00,
   0x34, 0x00, 0x00, 0x00, 0x01, 0x4d, 0x00, 0x20, 0x07, 0x7f, 0x00, 0x00, 0x31,
   0x00, 0x00, 0x07, 0x00, 0x3a, 0x00, 0x20, 0xe0, 0x0f, 0x00, 0x06, 0x10, 0x00,
   0x00, 0x82};

struct IsaData
{
    IsaData(): binary(nullptr),
               size(0),
               options(nullptr) {}

    IsaData(uint8_t *in_binary,
            size_t in_size,
            char *in_options): binary(in_binary),
                               size(in_size),
                               options(in_options) {}
    
    uint8_t *binary;
    size_t size;
    char *options;
};
typedef std::vector<IsaData> IsaArray;

using CMRT_UMD::CmSampler;
using CMRT_UMD::CmSampler8x8;
class KernelTest: public CmTest
{
public:
    KernelTest(): m_program(nullptr), m_kernel(nullptr) {}

    ~KernelTest() {}

    int32_t LoadDestroyProgram(uint8_t *isa_code,
                               uint32_t size,
                               const char *options)
    {
        if (nullptr == options)
        {
            options = "nojitter";
        }
        int32_t result = m_mockDevice->LoadProgram(isa_code, size, m_program,
                                                   options);
        if (result != CM_SUCCESS)
        {
            return result;
        }
        return m_mockDevice->DestroyProgram(m_program);
    }//================================================

    //*-------------------------------------------------------------------------
    //| Selects ISA code, size and options from an array and loads them as a
    //| CmProgram.
    //*-------------------------------------------------------------------------
    int32_t SelectLoadDestroyProgram(IsaArray *isa_array)
    {
        IsaData *isa_data = FindIsaData(isa_array);
        return LoadDestroyProgram(isa_data->binary,
                                  static_cast<uint32_t>(isa_data->size),
                                  isa_data->options);
    }

    //*-------------------------------------------------------------------------
    //| Creates a kernel from the default ISA code.
    //*-------------------------------------------------------------------------
    int32_t CreateKernel(const char *kernel_name)
    {
        if (nullptr == kernel_name)  // Tests the return value if CmProgram is invalid.
        {
            return m_mockDevice->CreateKernel(nullptr, "DoNothing", m_kernel,
                                              nullptr);
        }
        int32_t result = CreateKernelFromDefaultIsa(kernel_name);
        if (CM_SUCCESS == result)
        {
            uint32_t spill_size = 0;
            int32_t temp_result = m_kernel->QuerySpillSize(spill_size);
            EXPECT_EQ(CM_FAILURE, temp_result);
        }
        DestroyKernel();
        return result;
    }//===============

    int32_t SetArgument(uint32_t index,
                        size_t size,
                        const void *value)
    {
        int32_t result = CreateKernelFromDefaultIsa("DoNothing");
        EXPECT_EQ(CM_SUCCESS, result);

        result = m_kernel->SetKernelArg(index, size, value);
        DestroyKernel();
        return result;
    }//===============

    //*-------------------------------------------------------------------------
    //| Sets sampler BTI for CmSampler.
    //*-------------------------------------------------------------------------
    template<class SamplerType, class Function >
    int32_t SetSamplerBTI(int sampler_count,
                          uint32_t binding_table_index,
                          Function Create)
    {
        int32_t result = CreateKernelFromDefaultIsa("DoNothing");
        EXPECT_EQ(CM_SUCCESS, result);

        SamplerType *samplers[2];
        samplers[0] = samplers[1] = nullptr;

        for (int i = 0; i < sampler_count; ++i)
        {
           samplers[i] = Create();
           EXPECT_NE(nullptr, samplers[i]);
        }

        if (0 == sampler_count)
        {
            ++sampler_count;  // Test for nullptr;
        }
        SamplerIndex *sampler_index = nullptr;
        int32_t return_value = 0;
        for (int i = 0; i < sampler_count; ++i)
        {
            if (nullptr != samplers[i])
            {
                result = samplers[i]->GetIndex(sampler_index);
                EXPECT_EQ(CM_SUCCESS, result);
            }
            result = m_kernel->SetSamplerBTI(sampler_index,
                                             binding_table_index);
            if (0 == i)
            {
                return_value = result;
            }
            else
            {
                EXPECT_EQ(CM_FAILURE, result);
            }
        }
        
        for (int i = 0; i < sampler_count; ++i)
        {
            if (nullptr != samplers[i])
            {
                result = DestroySampler(samplers[i]);
                EXPECT_EQ(CM_SUCCESS, result);
            }
        }
        
        DestroyKernel();
        return return_value;
    }

protected:
    //*-------------------------------------------------------------------------
    //| Creates CmSampler.
    //*-------------------------------------------------------------------------
    CmSampler* CreateSampler()
    {
        CM_SAMPLER_STATE sampler_state;
        sampler_state.magFilterType = CM_TEXTURE_FILTER_TYPE_LINEAR;
        sampler_state.minFilterType = CM_TEXTURE_FILTER_TYPE_LINEAR;
        sampler_state.addressU = CM_TEXTURE_ADDRESS_CLAMP;
        sampler_state.addressV = CM_TEXTURE_ADDRESS_CLAMP;
        sampler_state.addressW = CM_TEXTURE_ADDRESS_CLAMP;
        CmSampler *sampler = nullptr;
        m_mockDevice->CreateSampler(sampler_state, sampler);
        return sampler;
    }

    //*-------------------------------------------------------------------------
    //| Creates CmSampler8x8.
    //*-------------------------------------------------------------------------
    CmSampler8x8* CreateSampler8x8()
    {
        CM_AVS_NONPIPLINED_STATE nonpipelined_state;
        nonpipelined_state.BypassXAF = nonpipelined_state.BypassYAF = 1;
        nonpipelined_state.DefaultSharpLvl = 255;
        nonpipelined_state.maxDerivative4Pixels = 7; 
        nonpipelined_state.maxDerivative8Pixels = 20;
        nonpipelined_state.transitionArea4Pixels = 4;
        nonpipelined_state.transitionArea8Pixels = 5;

        CM_AVS_STATE_MSG state_message;
        state_message.AvsState = &nonpipelined_state;
        state_message.AVSTYPE = 0;
        state_message.BypassIEF = 1;
        state_message.GainFactor = 44;
        state_message.GlobalNoiseEstm = 255;
        state_message.StrongEdgeThr = 8;
        state_message.WeakEdgeThr = 1;
        state_message.StrongEdgeWght = 7;
        state_message.RegularWght = 2;
        state_message.NonEdgeWght = 1;
        state_message.wR3xCoefficient = 6;
        state_message.wR3cCoefficient = 15;
        state_message.wR5xCoefficient = 9;
        state_message.wR5cxCoefficient = 8;
        state_message.wR5cCoefficient = 3;

        CM_SAMPLER_8X8_DESCR descriptor;
        descriptor.stateType = CM_SAMPLER8X8_AVS;
        descriptor.avs = &state_message;
  
        CmSampler8x8 *sampler8x8 = nullptr;
        m_mockDevice->CreateSampler8x8(descriptor, sampler8x8);
        return sampler8x8;
    }

    //*-------------------------------------------------------------------------
    //| Resets the default ISA array.
    //*-------------------------------------------------------------------------
    bool ResetDefaultIsaArray();

    //*-------------------------------------------------------------------------
    //| Sets pointers to ISA binaries in the default ISA array.
    //*-------------------------------------------------------------------------
    bool SetDefaultIsaArrayBinaries();

    //*-------------------------------------------------------------------------
    //| Sets sizs of ISA binaries in the default ISA array.
    //*-------------------------------------------------------------------------
    bool SetDefaultIsaArraySizes();

    // Array of default ISA data.
    IsaArray m_isaArray;

private:
    //*-------------------------------------------------------------------------
    //| Finds the index of the ISA data corresponding to the platform in test.
    //*-------------------------------------------------------------------------
    IsaData* FindIsaData(IsaArray *isa_array);

    int32_t CreateKernelFromDefaultIsa(const char *kernel_name)
    {
        ResetDefaultIsaArray();
        SetDefaultIsaArrayBinaries();
        SetDefaultIsaArraySizes();
        IsaData *current_isa_data = FindIsaData(&m_isaArray);
        int32_t result
                = m_mockDevice->LoadProgram(
                    current_isa_data->binary,
                    static_cast<uint32_t>(current_isa_data->size),
                    m_program, "nojitter");
        EXPECT_EQ(CM_SUCCESS, result);
        return m_mockDevice->CreateKernel(m_program, kernel_name, m_kernel,
                                          nullptr);
    }//============================================

    int32_t DestroyKernel()
    {
        int32_t result = CM_SUCCESS;
        if (nullptr != m_kernel)
        {
            result = m_mockDevice->DestroyKernel(m_kernel);
            EXPECT_EQ(CM_SUCCESS, result);
        }
        if (nullptr != m_program)
        {
            result = m_mockDevice->DestroyProgram(m_program);
            EXPECT_EQ(CM_SUCCESS, result);
        }
        return result;
    }//===============

    int32_t DestroySampler(CmSampler *sampler)
    {
        return m_mockDevice->DestroySampler(sampler);
    }

    int32_t DestroySampler(CmSampler8x8 *sampler)
    {
        return m_mockDevice->DestroySampler8x8(sampler);
    }

    CMRT_UMD::CmProgram *m_program;
    CMRT_UMD::CmKernel *m_kernel;
};

TEST_F(KernelTest, LoadDestroyProgram)
{
    ResetDefaultIsaArray();
    RunEach<int32_t>(CM_INVALID_COMMON_ISA,
                     [this]()
                     { return SelectLoadDestroyProgram(&m_isaArray); });

    SetDefaultIsaArrayBinaries();
    RunEach<int32_t>(CM_INVALID_COMMON_ISA,
                     [this]()
                     { return SelectLoadDestroyProgram(&m_isaArray); });

    SetDefaultIsaArraySizes();
    for_each(m_isaArray.begin(), m_isaArray.end(),
             [](IsaData &isa_data) { --isa_data.size; });
    RunEach<int32_t>(CM_SUCCESS,
                     [this]()
                     { return SelectLoadDestroyProgram(&m_isaArray); });

    for_each(m_isaArray.begin(), m_isaArray.end(),
             [](IsaData &isa_data) { ++isa_data.size; });  // Correct sizes.
    RunEach<int32_t>(CM_SUCCESS,
                     [this]()
                     { return SelectLoadDestroyProgram(&m_isaArray); });

    char options[CM_MAX_OPTION_SIZE_IN_BYTE + 1];
    for (int i = 0; i < CM_MAX_OPTION_SIZE_IN_BYTE; ++i)
    {
        options[i] = '0';
    }
    options[CM_MAX_OPTION_SIZE_IN_BYTE] = 0;
    char *options_ptr = options;  // Uses a pointer instead if an array name.
    for_each(m_isaArray.begin(), m_isaArray.end(),
             [options_ptr](IsaData &isa_data)
             { isa_data.options = options_ptr; });
    RunEach<int32_t>(CM_INVALID_ARG_VALUE,
                     [this]()
                     { return SelectLoadDestroyProgram(&m_isaArray); });

    return;
}//========

TEST_F(KernelTest, LoadWrongIsa)
{
    const uint32_t CODE_SIZE = sizeof(SKYLAKE_DONOTHING_ISA);
    uint8_t wrong_isa_code[CODE_SIZE];
    memcpy_s(wrong_isa_code, CODE_SIZE, SKYLAKE_DONOTHING_ISA, CODE_SIZE);
    wrong_isa_code[0x23] = 0xff;
    uint8_t *wrong_isa_code_ptr = wrong_isa_code;

    ResetDefaultIsaArray();
    auto SetIsaArray = [wrong_isa_code_ptr, CODE_SIZE](IsaData &isa_data) {
        isa_data.binary = wrong_isa_code_ptr;
        isa_data.size = CODE_SIZE; };
    for_each(m_isaArray.begin(), m_isaArray.end(), SetIsaArray);

    RunEach<int32_t>(CM_INVALID_GENX_BINARY,
                     [this]()
                     { return SelectLoadDestroyProgram(&m_isaArray); });
    return;
}//========

TEST_F(KernelTest, CreateKernel)
{
    RunEach<int32_t>(CM_FAILURE,
            [this]() { return CreateKernel("wrong_name"); });

    RunEach<int32_t>(CM_NULL_POINTER,
            [this]() { return CreateKernel(nullptr); });
    return;
}//========

TEST_F(KernelTest, SetArgument)
{
    int arg0_value = 10;
    void *arg0_ptr = &arg0_ptr;

    RunEach<int32_t>(CM_SUCCESS,
                     [this, arg0_ptr]() { return SetArgument(0, sizeof(int),
                                                             arg0_ptr); });
    RunEach<int32_t>(CM_INVALID_ARG_INDEX,
                     [this, arg0_ptr]() { return SetArgument(2, sizeof(int),
                                                             arg0_ptr); });
    RunEach<int32_t>(CM_INVALID_ARG_SIZE,
                     [this, arg0_ptr]() { return SetArgument(0, sizeof(int) + 1,
                                                             arg0_ptr); });
    RunEach<int32_t>(CM_INVALID_ARG_SIZE,
                     [this, arg0_ptr]() { return SetArgument(0, sizeof(int) - 1,
                                                             arg0_ptr); });
    RunEach<int32_t>(CM_INVALID_ARG_SIZE,
                     [this, arg0_ptr]()
                     { return SetArgument(0, 0, arg0_ptr); });
    RunEach<int32_t>(CM_INVALID_ARG_VALUE,
                     [this, arg0_ptr]() { return SetArgument(0, sizeof(int),
                                                             nullptr); });
    return;    
}//========

TEST_F(KernelTest, SetSamplerBTI)
{
    auto CreateSampler = [this]() { return this->CreateSampler(); };

    RunEach<int32_t>(CM_NULL_POINTER,
                     [this, &CreateSampler]() {
                         return SetSamplerBTI<CmSampler>(0, 5,
                                                         CreateSampler); });
    
    static const uint32_t MAX_INDEX = 15;
    RunEach<int32_t>(CM_KERNELPAYLOAD_SAMPLER_INVALID_BTINDEX,
                     [this, &CreateSampler]() {
                         return SetSamplerBTI<CmSampler>(1, MAX_INDEX + 1,
                                                         CreateSampler); });

    RunEach<int32_t>(CM_SUCCESS,
                     [this, &CreateSampler]() {
                         return SetSamplerBTI<CmSampler>(2, 5,
                                                         CreateSampler); });

    auto CreateSampler8x8 = [this]() { return this->CreateSampler8x8(); };

    RunEach<int32_t>(CM_KERNELPAYLOAD_SAMPLER_INVALID_BTINDEX,
                     [this, &CreateSampler8x8]() {
                         return SetSamplerBTI<CmSampler8x8>(
                             1, MAX_INDEX + 1, CreateSampler8x8); });

    RunEach<int32_t>(CM_SUCCESS,
                     [this, &CreateSampler8x8]() {
                         return SetSamplerBTI<CmSampler8x8>(
                             2, 5, CreateSampler8x8); });
    return;
}
